namespace SimpleWebServices.Xml
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Xml.Serialization;

    /// http://en.wikipedia.org/wiki/Xlink
    [XmlRoot("link")]
    public class XLink : ValueObject<XLink>
    {
        private XmlSerializerNamespaces _declarations;
        private string _type;

        public XLink()
        {
            this.RegisterProperty(x => x.Href);
            this.RegisterProperty(x => x.Title);
            this.RegisterProperty(x => x.Type);

            this._declarations = new XmlSerializerNamespaces();
            this._declarations.Add("xlink", "http://www.w3.org/1999/xlink");
        }

        [XmlNamespaceDeclarations]
        public XmlSerializerNamespaces XmlNamespaceDeclarations
        {
            get
            {
                return this._declarations;
            }

            set
            {
                this._declarations = value;
            }
        }

        [XmlAttribute("href", Namespace = "http://www.w3.org/1999/xlink")]
        public string Href
        {
            get;
            set;
        }

        [XmlAttribute("title", Namespace = "http://www.w3.org/1999/xlink")]
        public string Title
        {
            get;
            set;
        }

        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "XLink types are lower case.")]
        [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The naming is intentionally the same as XLink.")]
        [XmlAttribute("type", Namespace = "http://www.w3.org/1999/xlink")]
        public string Type
        {
            get
            {
                return this._type;
            }

            set
            {
                if (null != value)
                {
                    if (0 == value.Length)
                    {
                        throw new ArgumentOutOfRangeException("value");
                    }

                    value = value.ToLowerInvariant();

                    switch (value)
                    {
                        case "simple":
                        case "extended":
                        case "locator":
                        case "arc":
                        case "resource":
                        case "title":
                            break;

                        default:
                            throw new ArgumentOutOfRangeException("value");
                    }
                }

                this._type = value;
            }
        }
    }
}